What is IoC
Inversion of Control (IoC) is a design principle in software engineering which transfers the control of objects or portions of a program to a container or framework. We can achieve IoC through various mechanisms such as the Service Locator pattern, Factory pattern, and Dependency Injection (DI).
What is DI
Dependency injection (DI) is a pattern to implement IoC. There are mainly three types of DI:
- Constructor Injection
- Setter Injection
- Field Injection
A simple example
In traditional code, objects generally create and manage their dependencies
class Repository {
// ...
}
class Service {
// Service class create the repository instance
// If we change the code of the Repository, we need to change the Service code too.
private Repository repository = new Repository();
// ...
}
Make use of IoC, the Service class no longer creates the Repository instance. The External container will take responsibility for this.
class Repository {
// ...
}
class Service {
private Repository repository;
// Inject a Repository instance through the constructor
public Service(Repository repository) {
this.repository = repository;
}
}
Advantages
- Reducing the coupling between codes
- Make the program more modularity
- Greater ease of testing
- More flexible
Spring IoC container
The Spring IoC container creates objects, wires them together, configures them, and manages their complete lifecycle from creation to destruction. Separate configuration and application code allow the application code to focus on the business logic rather than on infrastructure concerns.
There are two ways to configure the objects: XML and Annotation
XML based configuration
The usual file path: src/main/resources/applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans">
<!-- Define Repository Bean -->
<bean id="repository" class="Repository"/>
<!-- Define Service Bean, and inject the Repository Bean -->
<bean id="service" class="Service">
<constructor-arg ref="repository"/>
</bean>
</beans>
Load configuration file:
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Repository respository = context.getBean(Respository.class);
Service service = context.getBean(Service.class);
// respository.dosomething();
// service.dosomething();
}
}
Annotation based configuration
the usual file path: src/main/java/com/example/config/AppConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuuration
public class AppConfig {
@Bean
public Repository repository() {
return new Repository();
}
@Bean
public Service service() {
return new Service(repository());
}
}
Load configuration file:
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Repository respository = context.getBean(Respository.class);
Service service = context.getBean(Service.class);
// respository.dosomething();
// service.dosomething();
}
}
Conclusion
IoC is one of the core concepts of Spring, enabling the framework to manage object creation and dependencies efficiently through its IoC container. This approach promotes loose coupling, modularity, and easier testing, making it a cornerstone of Spring's architecture and a key reason for its flexibility and widespread use in enterprise applications.